/*
 * Copyright 2010 J Patrick Davenport
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package v4view.web;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;

import java.io.IOException;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

import v4view.web.Table.Frame;
import v4view.web.Table.HeadBodyFoot;
import v4view.web.Table.Rules;

public class TableTests extends TableElementTests {
	private Table					t		= new Table();
	final MockHttpServletRequest	request	= new MockHttpServletRequest();
	final MockHttpServletResponse	resp	= new MockHttpServletResponse();

	@Before
	public void init() {
		this.t.setPrettyPrint(true);
		this.t.setRequest(this.request);
		this.t.setResponse(this.resp);
	}

	@Test
	public void setPositiveRule() throws IOException {
		final Rules all = Rules.ALL;
		this.t.setRules(all);
		final Rules rules = this.t.getRules();
		assertEquals(all, rules);
		this.t.addPageElement(new Tr());
		this.t.load();
		this.t.render();

		final String contentAsString = this.resp.getContentAsString();
		assertTrue(contentAsString.contains("rules=\"all\""));
	}

	@Test
	public void setNegativeRule() throws IOException {
		this.t.setRules(null);
		final Rules rules = this.t.getRules();
		assertEquals(null, rules);
		this.t.addPageElement(new Tr());
		this.t.load();
		this.t.render();

		final String contentAsString = this.resp.getContentAsString();
		System.out.println(contentAsString);
		assertTrue(!contentAsString.contains("rules="));
	}

	@Test
	public void checkCellPadding() {
		final Integer cellPadding = this.t.getCellPadding();
		assertNull(cellPadding);
		Table result = this.t.setCellPadding(10);
		assertEquals(this.t, result);
		assertEquals(Integer.valueOf(10), this.t.getCellPadding());

		result = this.t.setCellPadding(20);
		assertEquals(this.t, result);
		assertEquals(Integer.valueOf(20), this.t.getCellPadding());
	}

	@Test
	public void checkCellSpacing() {
		final Integer cellPadding = this.t.getCellSpacing();
		assertNull(cellPadding);
		Table result = this.t.setCellSpacing(5);
		assertEquals(this.t, result);
		assertEquals(Integer.valueOf(5), this.t.getCellSpacing());

		result = this.t.setCellSpacing(59);
		assertEquals(this.t, result);
		assertEquals(Integer.valueOf(59), this.t.getCellSpacing());
	}

	@Test
	public void checkSetFrameWithNull() throws IOException {
		Table result = this.t.setFrame(null);
		assertEquals(null, this.t.getFrame());
		this.t.load();
		this.t.render();
		final String contentAsString = this.resp.getContentAsString();
		assertTrue(!contentAsString.contains("frames="));

		final Frame above = Frame.ABOVE;
		result = this.t.setFrame(above);
		assertEquals(this.t, result);
		assertEquals(above, this.t.getFrame());
	}

	@Test
	public void checkBorder() {
		final Integer border = this.t.getBorder();
		assertNull(border);

		final Table setBorder = this.t.setBorder(null);
		assertEquals(this.t, setBorder);

		this.t.setBorder(10);
		assertEquals(Integer.valueOf(10), this.t.getBorder());
	}

	@Test
	public void checkAddHead() {
		assertNull(this.t.getHead());
		this.t.addPageElement(new THead());
		assertNotNull(this.t.getHead());

		// The second add will be ignored.
		this.t.addPageElement(new THead());
		assertEquals(1, this.t.getNumberOfChildren());
	}

	@Test
	public void checkBodies() {
		final List<TBody> bodies = this.t.getBodies();
		assertTrue(bodies != null);

		// Makes sure it's living up to its contract.
		boolean threwModifyException = false;
		try {
			bodies.add(new TBody());
		} catch (final UnsupportedOperationException ex) {
			threwModifyException = true;
		}
		assertTrue(threwModifyException);
		assertEquals(0, bodies.size());

		this.t.addPageElement(new TBody().setElementId("body1"));
		final List<TBody> updatedBodies = this.t.getBodies();
		assertTrue(CollectionUtils.isNotEmpty(updatedBodies));
	}

	@Test
	public void checkGetFoot() {
		TFoot foot = this.t.getFoot();
		assertNull(foot);

		final TFoot element = new TFoot();
		this.t.addPageElement(element);
		foot = this.t.getFoot();
		assertNotNull(foot);
		assertEquals(element, foot);
		assertNotNull(foot.getElementId());
	}

	@Test
	public void checkCreateHeadBodyFoot() {
		final HeadBodyFoot createOrGetHeadBodyFoot = this.t.createOrGetHeadBodyFoot();
		assertNotNull(createOrGetHeadBodyFoot);
		assertEquals(this.t.getHead(), createOrGetHeadBodyFoot.getHead());
		assertEquals(this.t.getBodies(), createOrGetHeadBodyFoot.getBodies());
		assertEquals(this.t.getFoot(), createOrGetHeadBodyFoot.getFoot());
	}

	@Test
	public void checkFindHeadBodyFoot() throws IOException {
		final THead head = new THead();
		this.t.addPageElement(head);

		final TFoot foot = new TFoot();
		this.t.addPageElement(foot);

		final TBody body = new TBody();
		this.t.addPageElement(body);

		final HeadBodyFoot createOrGetHeadBodyFoot = this.t.createOrGetHeadBodyFoot();
		assertNotNull(createOrGetHeadBodyFoot);
		assertEquals(this.t.getHead(), head);
		assertTrue(this.t.getBodies().contains(body));
		assertEquals(this.t.getBodies().size(), 1);
		assertEquals(this.t.getFoot(), foot);

		this.t.setPrettyPrint(true);
		this.t.load();

		this.t.render();
		final String contentAsString = this.resp.getContentAsString();
		System.out.println(contentAsString);
	}

	@Test
	public void checkCaptionAdd() throws IOException {
		this.t.setCaption(new Caption("Hello"));
		this.t.load();
		this.t.render();
		final String response = this.resp.getContentAsString();
		System.out.println("checkCaptionAdd: " + response);
		assertTrue(response.contains("<caption>\r\n\t\tHello\r\n\t</caption>"));
	}

	@Test
	public void checkCaption() {
		final String text = "My name is not Flow";
		final Caption caption = new Caption(text);
		this.t.setCaption(caption);
		assertEquals(this.t.getCaption(), caption);
		assertEquals(((Content) this.t.getCaption().getChildren().get(0)).getContent(), text);

		final Table setCaption = this.t.setCaption((Caption) null);
		assertEquals(this.t, setCaption);
	}

	@Test
	public void checkStringCaption() {
		final String text = "My name is not Flow";
		this.t.setCaption(text);
		assertEquals(((Content) this.t.getCaption().getChildren().get(0)).getContent(), text);

		final Table setCaption = this.t.setCaption((String) null);
		assertEquals(this.t, setCaption);
	}

	@Override
	protected TableElement getElement() {
		return this.t;
	}

}
